package com.qf.utils;

import com.qf.mapper.UserMapper;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;

public class MapperUtils {

    //静态单例模式（随着类的加载而加载）
    private static SqlSessionFactory factory;

    //这个变量一定不可以在成员位置保存对象，线程不安全的，作用域只能是放法级别（线程私有）
//    private static SqlSession sqlSession;

    private static ThreadLocal<SqlSession> tl = new ThreadLocal<>();

    static {
        try(InputStream is = Resources.getResourceAsStream("mybatis.xml")) {

            SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();

            //通过builder对象获取SqlSessionFactory
            factory = builder.build(is);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 如果要手动管理事务，使用这种方式获取SqlSession
     * @param autoCommit
     * @return
     */
    public static SqlSession openSession(boolean autoCommit){
        return factory.openSession(autoCommit);
    }

    /**
     * 不需要手动管理事务，使用这个方法获取SqlSession
     * @return
     */
    public static SqlSession openSession(){
        return openSession(true);
    }

    /**
     * 如果自动提交，调用这个方法
     * @param cls
     * @param <T>
     * @return
     */
    public static<T> T getMapper(Class<T> cls){
        return getMapper(cls,true);
    }

    /**
     * 如果要手动提交，调用这个方法，并且autoCommit传入false
     * @param cls
     * @param autoCommit
     * @param <T>
     * @return
     */
    public static<T> T getMapper(Class<T> cls,boolean autoCommit){

        SqlSession sqlSession = tl.get();

        if (sqlSession == null) {
            if (autoCommit) {
                sqlSession = openSession();
            }else {
                sqlSession = openSession(false);
            }

            //存入线程域对象中
            tl.set(sqlSession);
        }

        return sqlSession.getMapper(cls);
    }

    public static void close(){
        SqlSession sqlSession = tl.get();
        if (sqlSession != null) {
            sqlSession.close();

            //一定要将其和当前线程解绑(解决内存泄漏问题)
            tl.remove();
        }
    }
    public static void commit(){
        SqlSession sqlSession = tl.get();
        if (sqlSession != null) {
            sqlSession.commit();
        }
    }
    public static void rollback(){
        SqlSession sqlSession = tl.get();
        if (sqlSession != null) {
            sqlSession.rollback();
        }
    }
}
